%%%-------------------------------------------------------------------
%%% @author liuwentao
%%% @doc
%%%     列表解析工具
%%% @end
%%% Created : 19. 7月 2021 15:04
%%%-------------------------------------------------------------------
-module(list_util).
-author("liuwentao").

-export([
    keysdelete/2
    , delete/2
    , member/2
    , keysort/2
    , keyresort/2
    , mkeysort/2
    , mkeysort2/2
    , mkeyresort/2
    , sort/1
    , resort/1
    , index/2
    , index/3
    , keyindex/3
    , keyindex/4
    , implode/2
    , rand/1
    , rand_more/2
    , rand_more2/2
    , rand_more_repeat/2
    , keyrand/2
    , keyrand_more/3
    , keyrand_more2/3
    , find/3
    , keyfind/2
    , keyfind/3
    , keyfind/4
    , keyfind_list/3
    , ukeymerge/3
    , keyfind_all/3
    , keyfind_less_all/3
    , keydelete_all/3
    , keysfind_all/3
    , keysdelete_all/3
    , keysum/2
    , keyfind_all_and_sum/4
    , mkeyfind_all_and_sum/4
    , key2list/2
    , key2list/3
    , keyupdate/4
    , keyadd/4
    , split/2
    , diff_split/3
    , diff/2
    , is_diff/2
    , nth/2
    , nthdelete/2
    , nthupdate/3
    , verify_uniq/2
    , find_index/2
    , filter_list/1
    , keymax/2
    , keymin/2
    , sublist/3
    , ustore/2
    , umerge_add/2
    , group_by/2
    , set_list_element/3
    , delete_list_element/2
    , list_add/2
    , key_replace/3
    , list_replace/3
    , list_replace_one/3
    , number_member/2
    , mix_key_val/2
    , shuffle/1
    , filter_replicat/1
    , assets_list_add/2
    , is_repetition/1
    , is_urepetition/1
    , concat/2
    , max/2
    , min/2
    , multikeyfind/2
    , multikeystore/3
    , forward/2
    , loop_index/2
    , mkeystore/3
]).
-include("common.hrl").

%% ==============================================================================
%% @doc 从西游迁移过来的代码
%% ==============================================================================

%%%% @spec min(List) -> Value
%%%% List = list()
%%%% @doc 空列表不报错的lists:min
%%min([]) -> [];
%%min(List) -> lists:min(List).
%%
%%%% @spec min(List, Default) -> Value
%%%% List = list()
%%%% @doc 空列表不报错的lists:min
%%min(List, _Def) when is_list(List) andalso List =/= [] ->
%%    lists:min(List);
%%min(_, Def) -> Def.
%%
%%%% @spec max(List) -> Value
%%%% List = list()
%%%% @doc 空列表不报错的lists:max
%%max(List, _Def) when is_list(List) andalso List =/= [] ->
%%    lists:max(List);
%%max(_, Def) -> Def.

%% @spec delete(DelList, List) -> List2
%% DelList = List = List2 = list()
%% @doc 删除多个元素
delete(_DelList, []) -> [];
delete([Elem | R], List) ->
    delete(R, lists:delete(Elem, List));
delete([], List) -> List.

%% @spec keysdelete(TList, KList) -> TList
%% TList = [tuple()]
%% KList = [int()]
%% @doc 根据多个keys值删除tuplelist
keysdelete(TList, KList) ->
    keysdelete_f1(TList, KList).

keysdelete_f1(TList, []) -> TList;
keysdelete_f1(TList, [K | T]) ->
    keysdelete_f1(lists:keydelete(K, 1, TList), T).


%% @spec keymax(TList, Key) -> tuple()
%% TList = [tuple()]
%% KList = [int()]
%% @doc 根据多个keys值删除tuplelist
keymax([H | T], Key) ->
    keymax(T, element(Key, H), H, Key).

keymax([H | T], Max, Tpl, Key) ->
    Elem = element(Key, H),
    if Elem > Max -> keymax(T, Elem, H, Key);
        true -> keymax(T, Max, Tpl, Key)
    end;
keymax([], _Max, Tpl, _Key) -> Tpl.

keymin([H | T], Key) ->
    keymin(T, element(Key, H), H, Key).

keymin([H | T], Max, Tpl, Key) ->
    Elem = element(Key, H),
    if Elem < Max -> keymin(T, Elem, H, Key);
        true -> keymin(T, Max, Tpl, Key)
    end;
keymin([], _Max, Tpl, _Key) -> Tpl.


%% @spec verify_uniq(TPs, KeyPos)-> Tps2
%% KeyPos = int()
%% TPs = [ tuple() ]
%% @doc 校验tuple list 唯一性( TODO:会过滤掉重复主键的tuple主要用于过滤重复的物品
verify_uniq(TPs, KeyPos) ->
    verify_uniq(TPs, KeyPos, []).

verify_uniq([], _KeyPos, RtnL) ->
    RtnL;
verify_uniq([Tp | T], KeyPos, RtnL) ->
    OneElement = erlang:element(KeyPos, Tp),
    case lists:keyfind(OneElement, KeyPos, RtnL) of
        false ->
            verify_uniq(T, KeyPos, [Tp | RtnL]);
        _Finded ->
            verify_uniq(T, KeyPos, RtnL)
    end.

%% @spec split(List1) -> List2
%% H = Any()
%% @doc 过滤重复元素
filter_list(L) ->
    filter_list(L, []).

filter_list([], L) -> L;
filter_list([H | T], L) ->
    case lists:member(H, L) of
        true ->
            filter_list(T, L);
        false ->
            filter_list(T, [H | L])
    end.

%% @spec split(N, List) -> {List1, List2}
%% N = int()
%% List = List1 = List2 = list()
%% @doc N比List长的时候返回 {List, []} 的lists:split()
split(N, List) when is_integer(N), N >= 0, is_list(List) ->
    split(N, List, []);
split(N, List) ->
    erlang:error(badarg, [N, List]).

split(0, L, R) ->
    {lists:reverse(R, []), L};
split(N, [H | T], R) ->
    split(N - 1, T, [H | R]);
split(_N, [], R) ->
    split(0, [], R).

%% @spec keysort(Key, L) -> L2
%% @doc 其实就是lists:keysort/2
keysort(Key, L) ->
    lists:keysort(Key, L).

%% @spec keyresort(Key, L) -> L2
%% @doc lists:keysort/2的反排序
keyresort(Key, L) ->
    lists:reverse(lists:keysort(Key, L)).

%% @spec mkeysort(KeyPoss::[int()], List::[tuple()]) -> [tuple()]
%% @doc 多键值排序
%%
%% <pre> list_util:mkeysort([2,1], [{1,2,3}, {2, 1, 3}, {2, 2, 2}]).
%% [{2, 1, 3}, {1, 2, 3}, {2, 2, 2}]</pre>
mkeysort(_Keys, []) -> [];
mkeysort(_Keys, [F]) -> [F];
mkeysort([], TupleList) when is_list(TupleList) -> TupleList;
mkeysort([Key], TupleList) when is_list(TupleList) -> lists:keysort(Key, TupleList);
mkeysort([Key | Keys], TupleList) when is_list(TupleList) ->
    [F | T] = lists:keysort(Key, TupleList),
    mkeysort_fun(T, Key, Keys, element(Key, F), [F], []). %% 分组
mkeysort_fun([], _Key, Keys, _Val, Buff, Res) ->
    NewBuff = mkeysort(Keys, Buff),
    Res ++ NewBuff;
mkeysort_fun([F | T], Key, Keys, Val, Buff, Res) ->
    case element(Key, F) of
        Val -> mkeysort_fun(T, Key, Keys, Val, [F | Buff], Res);  %% 同一组的放进buff
        Val2 ->
            NewBuff = mkeysort(Keys, Buff),
            mkeysort_fun(T, Key, Keys, Val2, [F], Res ++ NewBuff)
    end.

%% @spec mkeysort(KeyPoss::[int()], List::[tuple()]) -> [tuple()]
%% @doc 支持正反逻辑多键值排序
%%
%% <pre> list_util:mkeysort2([{s,2},{r,1}], [{1,2,3}, {2, 1, 3}, {2, 2, 2}]).
%% [{2, 1, 3}, {2, 2, 2}, {1, 2, 3}]</pre>
mkeysort2(_Keys, []) -> [];
mkeysort2(_Keys, [F]) -> [F];
mkeysort2([], TupleList) when is_list(TupleList) -> TupleList;
mkeysort2([Key], TupleList) when is_list(TupleList) -> mkeysort2_fun3(Key, TupleList);
mkeysort2([Key | Keys], TupleList) when is_list(TupleList) ->
    {_, Key2} = Key,
    [F | T] = mkeysort2_fun3(Key, TupleList),
    mkeysort_fun2(T, Key, Keys, element(Key2, F), [F], []). %% 分组
mkeysort_fun2([], _Key, Keys, _Val, Buff, Res) ->
    NewBuff = mkeysort2(Keys, Buff),
    Res ++ NewBuff;
mkeysort_fun2([F | T], Key, Keys, Val, Buff, Res) ->
    {_, Key2} = Key,
    case element(Key2, F) of
        Val -> mkeysort_fun2(T, Key, Keys, Val, [F | Buff], Res);  %% 同一组的放进buff
        Val2 ->
            NewBuff = mkeysort2(Keys, Buff),
            mkeysort_fun2(T, Key, Keys, Val2, [F], Res ++ NewBuff)
    end.

%% 分正反排序
mkeysort2_fun3({s, Key}, Tuplelist) ->
    lists:keysort(Key, Tuplelist);
mkeysort2_fun3({r, Key}, Tuplelist) ->
    lists:reverse(lists:keysort(Key, Tuplelist)).

%% @spec mkeyresort(KeyPoss::[int()], List::[tuple()]) -> [tuple()]
%% @doc 多键值反排序
mkeyresort(Keys, L) ->
    lists:reverse(mkeysort(Keys, L)).

%% @spec sort(L) -> L2
%% @doc 由小到大排序
sort(L) -> lists:sort(L).

%% @spec resort(L) -> L2
%% @doc 由大到小排序
resort(L) -> lists:reverse(lists:sort(L)).

%% @spec index(Elem::term(), List::list()) -> int()
%% @doc 获取元素在数组中索引
index(Elem, List) -> index_loop(Elem, List, 1, 0).
%% @spec index(Elem::term(), List::list(), Def::int()) -> int()
%% @doc 获取元素在数组中索引
index(Elem, List, Def) -> index_loop(Elem, List, 1, Def).
index_loop(_Elem, [], _I, Def) -> Def;
index_loop(Elem, [E | T], I, Def) ->
    case Elem =:= E of
        true -> I;
        false -> index_loop(Elem, T, I + 1, Def)
    end.

%% @spec keyindex(Key, N, List) -> int()
%% @doc 根据key值获取元素在数组中索引，如果没有返回0
keyindex(Key, N, List) -> keyindex(Key, N, List, 0).

%% @spec keyindex(Key, N, List, Def) -> int() | Def
%% @doc 根据key值获取元素在数组中索引
keyindex(Key, N, List, Def) ->
    keyindex_f1(Key, N, List, 1, Def).
keyindex_f1(_Key, _N, [], _I, Def) -> Def;
keyindex_f1(Key, N, [E | T], I, Def) ->
    case element(N, E) of
        Key -> I;
        _ -> keyindex_f1(Key, N, T, I + 1, Def)
    end.

%% @spec implode(S::term(), L::list()) -> list()
%% @doc 插入元素到列
implode(S, L) ->
    implode_fun(L, S, []).
implode_fun([], _S, _Res) -> <<>>;
implode_fun([Key], _S, Res) ->
    lists:reverse([Key | Res]);
implode_fun([Key | T], S, Res) ->
    implode_fun(T, S, [S, Key | Res]).


%% @spec rand(L::list()) -> undefined | term()
%% @doc 从一个list中随机取出一项
rand([]) -> undefined;
rand([I]) -> I;
rand(List) ->
    Idx = util:rand(1, length(List)),
    lists:nth(Idx, List).

%%@spec rand_more(Tuplelist, Num) -> [undefined | tuple()]
%% TupleList = [tuple()]
%% Num = integer()
%%@doc 列表随机取出Num个不重复的数据
rand_more(List, Num) ->
    rand_more_f1(List, erlang:max(0, Num), []).
rand_more_f1(_, 0, Result) -> Result;
rand_more_f1(List, Num, Result) ->
    Tuple = rand(List),
    rand_more_f1(lists:delete(Tuple, List), Num - 1, [Tuple | Result]).

%%@spec rand_more2(Tuplelist, Num) -> [tuple()]
%% TupleList = [tuple()]
%% Num = integer()
%%@doc 列表随机取出Num个不重复的数据,如果列表长度不够,直接返回整个列表,不会填undefined
rand_more2(List, Num) ->
    case length(List) < Num of
        true -> List;
        _ -> rand_more_f1(List, erlang:max(0, Num), [])
    end.
%%@spec rand_more_repeat(Tuplelist, Num) -> [tuple()]
%% TupleList = [tuple()]
%% Num = integer()
%%@doc 列表随机取出Num个数据,可重复.
rand_more_repeat([], _Num) -> [];
rand_more_repeat(List, Num) ->
    rand_more_repeat_f1(List, erlang:max(0, Num), []).
rand_more_repeat_f1(_, 0, Result) -> Result;
rand_more_repeat_f1(List, Num, Result) ->
    Tuple = rand(List),
    rand_more_repeat_f1(List, Num - 1, [Tuple | Result]).

%% @spec keyrand(TupleList, N) -> undefined | tuple()
%% TupleList = [tuple()]
%% @doc 从一个list中根据N中数值概率取出一项
keyrand([], _N) -> undefined;
keyrand(List, N) ->
    Sum = keyrand_f1(List, N, 0),
    if
        Sum < 1 ->
            undefined;
        true ->
            Rand = util:rand(1, Sum),
            keyrand_f2(List, N, Rand, 0)
    end.

keyrand_f1([], _N, Sum) -> Sum;
keyrand_f1([Tuple | T], N, Sum) ->
    keyrand_f1(T, N, Sum + element(N, Tuple)).
keyrand_f2([], _N, _Rand, _Sum) -> undefined;
keyrand_f2([Tuple | T], N, Rand, Sum) ->
    Rate = element(N, Tuple),
    case Rate + Sum >= Rand of
        true -> Tuple;
        false -> keyrand_f2(T, N, Rand, Sum + Rate)
    end.

%%@spec keyrand_more(Tuplelist, Nth, Num) -> [undefined | tuple()]
%% TupleList = [tuple()]
%% Nth = integer()
%% Num = integer()
%%@doc 列表以第Nth个元素数值，随机取出Num个不重复的数据
keyrand_more(List, Nth, Num) ->
    rand_more_f1(List, Nth, erlang:max(0, Num), []).
rand_more_f1(_, _, 0, Result) -> Result;
rand_more_f1(List, Nth, Num, Result) ->
    Tuple = keyrand(List, Nth),
    rand_more_f1(lists:delete(Tuple, List), Nth, Num - 1, [Tuple | Result]).

%%@spec keyrand_more(Tuplelist, Nth, Num) -> [undefined | tuple()]
%% TupleList = [tuple()]
%% Nth = integer()
%% Num = integer()
%%@doc 列表以第Nth个元素数值，随机取出Num个数据(重复取);少计算总数
keyrand_more2(List, Nth, Num) ->
    Sum = keyrand_f1(List, Nth, 0),
    rand_more2_f1(Sum, List, Nth, erlang:max(0, Num), []).
rand_more2_f1(_, _, _, 0, Result) -> Result;
rand_more2_f1(Sum, List, Nth, Num, Result) ->
    Rand = util:rand(1, Sum),
    % Tuple = keyrand(List, Nth),
    Tuple = keyrand_f2(List, Nth, Rand, 0),
    rand_more2_f1(Sum, List, Nth, Num - 1, [Tuple | Result]).

%% @spec find(Vals, List, Def) -> Def | Val
%% Vals = [term()]
%% List = [term()]
%% Def = term()
%% Val = term()
%% @doc 从List中查找Vals，如果有返回第一Val，如果没有返回Def，一般用在检查配置参数
find([], _List, Def) -> Def;
find([Val | T], List, Def) ->
    case lists:member(Val, List) of
        true -> Val;
        false -> find(T, List, Def)
    end.

%% @spec keyfind(Key, TupleList) -> undefined | term()
%% Key = atom()
%% TupleList = [{atom(), term()}]
%% @doc 返回Val值，其实就是 proplists:get_value 等同于 keyfind(Key, TupleList, undefined)
keyfind(Key, TupleList) ->
    keyfind(Key, TupleList, undefined).

%% @spec keyfind(Key, TupleList, Def) -> Def | term()
%% Key = atom()
%% TupleList = [{atom(), term()}]
%% @doc lists:keyfind返回Val值，其实就是 proplists:get_value
keyfind(Key, TupleList, Def) ->
    case lists:keyfind(Key, 1, TupleList) of
        false -> Def;
        {_, Val} -> Val
    end.

%% @spec keyfind(Key, Pos, TupleList, Def) -> Def | term()
%% Key = atom()
%% Pos = int()
%% TupleList = [{atom(), term()}]
%% @doc lists:keyfind返回Val值，其实就是 proplists:get_value
keyfind(Key, Pos, TupleList, Def) ->
    case lists:keyfind(Key, Pos, TupleList) of
        false -> Def;
        Val -> Val
    end.

%% @spec keyfind_list(KeyList, Pos, TupleList) -> list()
%% KeyList = list()
%% Pos = int()
%% TupleList = [{atom(), term()}]
%% @doc 查找一个key列表里面有的值,
%% 注意:如果TupleList里面有多个Key是一样的值的话,只返回一个,不会全部返回
%% 例如:
%% L = [{a,1},{b,2},{a,3},{c,4},{d,5}].
%% list_util:keyfind_list([a,b],1,L).
%% 结果为:[{a,1},{b,2}]
keyfind_list(KeyList, Pos, TupleList) ->
    keyfind_list_f1(KeyList, Pos, TupleList, []).
keyfind_list_f1([], _Pos, _TupleList, Result) -> lists:reverse(Result);
keyfind_list_f1([Key | T], Pos, TupleList, Result) ->
    case lists:keyfind(Key, Pos, TupleList) of
        false -> keyfind_list_f1(T, Pos, TupleList, Result);
        Val -> keyfind_list_f1(T, Pos, TupleList, [Val | Result])
    end.

%% @spec ukeymerge(N, TupleList1, TupleList2) -> TupleList3
%% N = int()
%% TupleList1 = [Tuple]
%% TupleList2 = [Tuple]
%% TupleList3 = [Tuple]
%% Tuple = tuple()
%% @doc lists_keymerge/3的无重复版本，TupleList2将替代TupleList1里拥有的
ukeymerge(N, TupleList1, TupleList2) ->
    ukeymerge_f1(N, lists:ukeysort(N, TupleList1), lists:ukeysort(N, TupleList2)).

ukeymerge_f1(N, [H1 | T1], [H2 | _] = L2) when element(N, H1) < element(N, H2) ->
    [H1 | ukeymerge_f1(N, T1, L2)];
ukeymerge_f1(N, [H1 | _] = L1, [H2 | T2]) when element(N, H1) > element(N, H2) ->
    [H2 | ukeymerge_f1(N, L1, T2)];
ukeymerge_f1(N, [_H1 | T1], [H2 | T2]) -> %% ==
    [H2 | ukeymerge_f1(N, T1, T2)];
ukeymerge_f1(_N, [], L2) -> L2;
ukeymerge_f1(_N, L1, []) -> L1.

%% @spec keyfind_all(Key, N, TupleList) -> NewTupleList
%% Key = term()
%% N = int()
%% TupleList = [Tuple]
%% NewTupleList = [Tuple]
%% @doc 找出所有键值相同的tuple
keyfind_all(Key, N, TupleList) ->
    [T || T <- TupleList, element(N, T) == Key].

keyfind_less_all(Key, N, TupleList) ->
    [T || T <- TupleList, element(N, T) =< Key].

%% @spec keysfind_all(Keys, N, TupleList) -> NewTupleList
%% Key = term()
%% Keys = [Key]
%% N = int()
%% TupleList = [Tuple]
%% NewTupleList = [Tuple]
%% @doc 找出所有的多个主键
keysfind_all(Keys, N, TupleList) ->
    [T || T <- TupleList, lists:member(element(N, T), Keys)].

%% @spec keysdelete_all(Keys, N, TupleList) -> NewTupleList
%% Key = term()
%% Keys = [Key]
%% N = int()
%% TupleList = [Tuple]
%% NewTupleList = [Tuple]
%% @doc 删除所有多个主键键值相同的tuple
keysdelete_all(Keys, N, TupleList) ->
    [T || T <- TupleList, not lists:member(element(N, T), Keys)].


%% @spec keydelete_all(Key, N, TupleList) -> NewTupleList
%% Key = term()
%% N = int()
%% TupleList = [Tuple]
%% NewTupleList = [Tuple]
%% @doc 删除所有键值相同的tuple
keydelete_all(Key, N, TupleList) ->
    [T || T <- TupleList, element(N, T) /= Key].

%% @spec keyfind_all_and_sum(Key, N, SumPos, TupleList) -> integer()
%% Key = term()
%% N = SumPos = int()
%% TupleList = [Tuple]
%% @doc 找出所有键值相同的tuple, 并计算SumPos位置的和
keyfind_all_and_sum(Key, N, SumPos, TupleList) ->
    keyfind_all_and_sum(Key, N, SumPos, TupleList, 0).
keyfind_all_and_sum(_Key, _N, _SumPos, [], Sum) -> Sum;
keyfind_all_and_sum(Key, N, SumPos, [Tuple | T], Sum) ->
    Sum2 = case element(N, Tuple) of
               Key -> element(SumPos, Tuple) + Sum;
               _ -> Sum
           end,
    keyfind_all_and_sum(Key, N, SumPos, T, Sum2).

%% @spec mkeyfind_all_and_sum(KeyList, N, SumPos, TupleList) -> integer()
%% KeyList = [term()]
%% N = SumPos = int()
%% TupleList = [Tuple]
%% @doc 找出所有键值相同的tuple, 并计算SumPos位置的和
mkeyfind_all_and_sum(KeyList, N, SumPos, TupleList) ->
    mkeyfind_all_and_sum(KeyList, N, SumPos, TupleList, 0).
mkeyfind_all_and_sum(_KeyList, _N, _SumPos, [], Sum) -> Sum;
mkeyfind_all_and_sum(KeyList, N, SumPos, [Tuple | T], Sum) ->
    Sum2 = case lists:member(element(N, Tuple), KeyList) of
               true -> element(SumPos, Tuple) + Sum;
               _ -> Sum
           end,
    mkeyfind_all_and_sum(KeyList, N, SumPos, T, Sum2).

%% @spec keysum(N, TupleList) -> integer()
%% N = int()
%% TupleList = [Tuple]
%% NewTupleList = [Tuple]
%% @doc tuple_list()的某值求和，lists:sum的tuple_list版
keysum(N, TupleList) ->
    keysum_f1(N, TupleList, 0).
keysum_f1(_N, [], Sum) -> Sum;
keysum_f1(N, [Tuple | T], Sum) ->
    keysum_f1(N, T, element(N, Tuple) + Sum).

%% @spec key2list(N, TupleList) -> [term()]
%% N = int()
%% TupleList = [Tuple]
%% @doc 取出tuple_list()的某字段，返回list
key2list(N, TupleList) ->
    [element(N, T) || T <- TupleList].

%% @spec key2list(N, TupleList, ResList) -> ResList2
%% N = int()
%% TupleList = [Tuple]
%% ResList = [term()]
%% ResList2
%% @doc 取出tuple_list()的某字段，返回list
key2list(_N, [], ResList) -> ResList;
key2list(N, [H | T], ResList) ->
    key2list(N, T, [element(N, H) | ResList]).

%% @spec keyupdate(Key, N, TupleList, IVList) -> TupleList2
%% Key = term()
%% N = int()
%% TupleList = [Tuple]
%% @doc 根据key更新tuple_list()里的元素的相关字段，返回list
keyupdate(Key, N, TupleList, IVList) ->
    case lists:keyfind(Key, N, TupleList) of
        false -> TupleList;
        T -> lists:keyreplace(Key, N, TupleList, lists:foldl(fun({I, V}, X) -> setelement(I, X, V) end, T, IVList))
    end.

%% @spec keyadd(Key, N, TupleList, IVList) -> TupleList2
%% Key = term()
%% N = int()
%% TupleList = [Tuple]
%% @doc 根据key更新tuple_list()里的元素的相关字段，返回list，没有检查是否能相加

keyadd(K, N, L, IVList) when is_integer(N), N > 0 ->
    keyadd3(K, N, L, IVList).

keyadd3(Key, Pos, [Tup | Tail], IVList) ->
    K = element(Pos, Tup),
    if K == Key ->
        New = lists:foldl(fun({I, V}, X) ->
            Elem = element(I, X),
            setelement(I, X, erlang:max(Elem + V, 0))
                          end, Tup, IVList),
        [New | Tail];
        true ->
            [Tup | keyadd3(Key, Pos, Tail, IVList)]
    end;
keyadd3(_, _, [], _) -> [].

%% @spec ustore(Elem, List) -> TupleList2
%% @doc 添加元素，不重复的elem
ustore(E, L) ->
    case lists:member(E, L) of
        true -> L;
        false -> [E | L]
    end.

%% @spec @(L1, L2) -> L3
%% L1 = [term()]
%% L2 = [term()]
%% L3 = [term()]
%% @doc 差集计算（L1存在并且L2不存在的元素
diff(L1, L2) ->
    diff_f1(L1, L2, []).

diff_f1([], _L2, Res) -> Res;
diff_f1([H | T], L2, Res) ->
    case lists:member(H, L2) of
        true -> diff_f1(T, L2, Res);
        false -> diff_f1(T, L2, [H | Res])
    end.

%% @doc 判断L1中元素是否有在L2中存在
member([], _) -> false;
member([H | T], List) ->
    case lists:member(H, List) of
        true -> true;
        false -> member(T, List)
    end.

%% @doc 判断L1数组中各值是否在L2中存在， 如存在返回false, 如不存在返回true
is_diff(L1, L2) ->
    case is_diff_1(L1, L2) of
        [] -> true;
        _ -> false
    end.


is_diff_1(L1, L2) ->
    is_diff_2(L1, L2, []).

is_diff_2([], _L2, Res) -> Res;
is_diff_2([H | T], L2, Res) ->
    case lists:member(H, L2) of
        true -> is_diff_2(T, L2, [H | Res]);
        false -> is_diff_2(T, L2, Res)
    end.


%% @spec nth(L, N) -> Elem | undefined
%% L = [term()]
%% N = int()
%% Elem = term()
%% @doc 获取第X位值
nth([], _N) -> undefined;
nth(_, N) when N < 1 -> undefined;
nth([H | _T], 1) -> H;
nth([_ | T], N) -> nth(T, N - 1).

%% @spec nthupdate(L, N, Val) -> L2
%% L = [term()]
%% N = int()
%% Val = term()
%% L2 = [term()]
%% @doc 按第X位更新
nthupdate(L, N, Val) ->
    tuple_to_list(setelement(N, list_to_tuple(L), Val)).

%% @spec nthdelete(L, M) -> L2
%% L = [term()]
%% N = int()
%% L2 = [term()]
%% @doc 按第X位删除
nthdelete(L, N) ->
    nthdelete_f1(L, N, 1, []).

nthdelete_f1([], _N, _I, Res) -> lists:reverse(Res);
nthdelete_f1([_H | T], N, N, Res) ->
    nthdelete_f1(T, N, N + 1, Res);
nthdelete_f1([H | T], N, I, Res) ->
    nthdelete_f1(T, N, I + 1, [H | Res]).

%% @spec diff_split(KeyPosFind, TL1, TL2) -> {UpNewL, SameL, NoneEl}
%% KeyPosFind = int() 对比的tuple 元素位置
%% TL1 = TL2 = [tuple(),...]
%% UpNewL = [tuple(),...] 变化+TL2新增列表
%% SameL  = [tuple(),...] T1, T2 中 tuple完全一致的列表
%% NoneEl = [tuple(),...] TL1存在，TL2中不存在的列表
%% @doc 按照tuple的指定键值，对比TL1, TL2 两个 tuple list , 拆分成三个列表
diff_split(KeyPosFind, TL1, TL2) ->
    diff_split(KeyPosFind, TL1, TL2, [], [], []).
diff_split(_KeyPosFind, [], T2Rest, UpNewL, SameL, NoneEL) ->
    {T2Rest ++ UpNewL, SameL, NoneEL};
diff_split(KeyPosFind, [HeadT | T], TL2, UpNewL, SameL, NoneEL) ->
    ElemVal = element(KeyPosFind, HeadT),
    case lists:keyfind(ElemVal, KeyPosFind, TL2) of
        false ->
            diff_split(KeyPosFind, T, TL2, UpNewL, SameL, [HeadT | NoneEL]);
        HeadT ->
            diff_split(KeyPosFind, T, lists:delete(HeadT, TL2), UpNewL, [HeadT | SameL], NoneEL);
        ElemtTL2 ->
            diff_split(KeyPosFind, T, lists:delete(ElemtTL2, TL2), [ElemtTL2 | UpNewL], SameL, NoneEL)
    end.

find_index(_Val, []) ->
    0;

find_index(Val, [E | T]) ->
    case Val >= E of
        true -> find_index(Val, T);
        false -> E
    end.

%% 加兼容开始位置大于list长度的情况
sublist(List, S, E) ->
    case S > length(List) of
        true -> [];
        _ -> lists:sublist(List, S, E)
    end.

%% @spec group_by(Pos, TupleList) -> [Val]
%% Pos = uint()
%% TupleList = [tuple()]
%% Val = term()
%% @doc 根据键值聚合，返回该键值的聚合值
group_by(Pos, TupleList) ->
    group_by(Pos, TupleList, []).

group_by(_Pos, [], Res) -> Res;
group_by(Pos, [E | T], Res) ->
    V = element(Pos, E),
    case lists:member(V, Res) of
        true -> group_by(Pos, T, Res);
        false -> group_by(Pos, T, [V | Res])
    end.

%% @spec set_list_element(Pos, List,Value) -> [Val]
%% Pos = uint()
%% List = [term()]
%% Val = term()
%% @doc 设置数组的某个值
set_list_element(N, List, Value) ->
    {L1, [_ToReplace | L2]} = lists:split(N - 1, List),
    L1 ++ [Value] ++ L2.

%% @spec delete_list_element(Pos, List) -> [Val]
%% Pos = uint()
%% List = [term()]
%% Val = term()
%% @doc 删除数组的某个值
delete_list_element(N, List) ->
    {L1, [_ToDelete | L2]} = lists:split(N - 1, List),
    L1 ++ L2.

%% list_replace(c,c1,[a,b,c,d,e,f]) -> [a,b,c1,d,e,f]
%% @doc 把[a,b,c,d,e,f]中的c替换成c1,位置不变
list_replace(Old, New, List) ->
    list_replace_f1(Old, New, List, []).

list_replace_f1(_Old, _New, [], R) -> lists:reverse(R);
list_replace_f1(Old, New, [Cur | List], R) ->
    case Old == Cur of
        true -> list_replace_f1(Old, New, List, [New | R]);
        false -> list_replace_f1(Old, New, List, [Cur | R])
    end.


%% list_replace_one(c,c1,[a,b,c,d,e,f]) -> [a,b,c1,d,e,f]
%% @doc 把[a,b,c,d,e,f]中的第一个c替换成c1,位置不变,注意列表里面有多少相同的值的话,只替换一个
list_replace_one(Old, New, List) ->
    list_replace_one_f1(Old, New, List, []).

list_replace_one_f1(_Old, _New, [], R) -> lists:reverse(R);
list_replace_one_f1(Old, New, [Cur | List], R) ->
    case Old == Cur of
        true -> lists:reverse(R) ++ [New | List];
        false -> list_replace_one_f1(Old, New, List, [Cur | R])
    end.

%% @spec number_member(Val, List) -> bool()
%% @doc 判断列表是否有相同的数字存在,这个是判断数值有别于lists:member,
number_member(Val, List) ->
    number_member_1(List, Val).
number_member_1([], _Val) -> false;
number_member_1([Val1 | _T], Val) when Val1 == Val -> true;
number_member_1([_Val1 | T], Val) -> number_member_1(T, Val).

%% @spec mix_key_val(List, List) -> list()
%% @doc 两个{key, val}的数据混合,相同Key的值会相加
mix_key_val(List, []) -> List;
mix_key_val(List, [{Key, Val} | T]) ->
    Val1 = list_util:keyfind(Key, List, 0),
    NList = lists:keystore(Key, 1, List, {Key, Val + Val1}),
    mix_key_val(NList, T).

%% 洗牌算法
shuffle(List) -> shuffle(List, []).
shuffle([], Acc) -> Acc;
shuffle(List, Acc) ->
    {Leading, [H | T]} = lists:split(util:rand(1, length(List)) - 1, List), %%rand:uniform(length(List))
    shuffle(Leading ++ T, [H | Acc]).


%%list去重
filter_replicat(List) ->
    filter_replicat(List, []).

filter_replicat([], List) ->
    List;
filter_replicat([H | Rest], List) ->
    case lists:member(H, List) of
        true ->
            filter_replicat(Rest, List);
        _ ->
            filter_replicat(Rest, [H | List])
    end.

%% @spec list_add(List1, List2)-> List3.
%% List1=List2=List3=[int, ...]
%% @doc 两个数组相加,返回值的数目与list1的相同
list_add(List1, List2) ->
    list_add_1(List1, List2, []).
list_add_1([], _List2, Result) -> lists:reverse(Result);
list_add_1([V1 | T1], [], Result) -> list_add_1(T1, [], [V1 | Result]);
list_add_1([V1 | T1], [V2 | T2], Result) -> list_add_1(T1, T2, [V1 + V2 | Result]).

%%两个资产列表合并成一个列表
assets_list_add([], Assets) -> Assets;
assets_list_add([{Atom, Val} | L], Assets) ->
    case lists:keyfind(Atom, 1, Assets) of
        {Atom, Val1} ->
            assets_list_add(L, lists:keyreplace(Atom, 1, Assets, {Atom, Val + Val1}));
        _ ->
            assets_list_add(L, [{Atom, Val} | Assets])
    end.

%% ==============================================================================
%% @doc 从星辰迁移过来的代码
%% ==============================================================================

%% --------------------
%% @doc 获取列表最大的元素，用于定制的数据结构，已有的lists不支持传入排序函数
%% Fun = fun(E1, E2) 排序函数，使用 E1 > E2
%% L 非空元素列表
%% 返回列表最大值
%% --------------------
-spec max(Fun :: function(), L :: list()) -> term().
max(CmpFun, [H | L]) ->
    max(CmpFun, L, H).
max(_CmpFun, [], M) -> M;
max(CmpFun, [H | L], M) ->
    NM = case CmpFun(M, H) of
             true -> M;
             false -> H
         end,
    max(CmpFun, L, NM).


%% --------------------
%% @doc 获取列表最大的元素，用于定制的数据结构，已有的lists不支持传入排序函数
%% Fun = fun(E1, E2) 排序函数，使用 E1 < E2
%% L 非空元素列表
%% 返回列表最大值
%% --------------------
-spec min(Fun :: function(), L :: list()) -> term().
min(CmpFun, [H | L]) ->
    min(CmpFun, L, H).
min(_CmpFun, [], M) -> M;
min(CmpFun, [H | L], M) ->
    NM = case CmpFun(M, H) of
             true -> M;
             false -> H
         end,
    min(CmpFun, L, NM).

%% --------------------
%% @doc 查找需要指定多个key的元素
%% 参考lists:keyfind
%% 返回列表中第一个匹配的项
%% --------------------
-spec multikeyfind(MultiKey :: tuple(), TupleList :: list()) -> tuple() | false.
multikeyfind(_MultiKey, []) -> false;
multikeyfind(MultiKey, [H | L]) ->
    case match_muilt_key(MultiKey, H) of
        true -> H;
        false -> multikeyfind(MultiKey, L)
    end.

%% --------------------
%% @doc 在列表对某个元素进行替换，如果元素不存在，则新增
%% 参考lists:keystore
%% 返回一个新的列表
%% --------------------
-spec multikeystore(MultiKey :: tuple(), TupleList :: list(), AddData :: tuple()) -> list().
multikeystore(MultiKey, TupleList, AddData) ->
    multikeystore(MultiKey, TupleList, AddData, []).

multikeystore(_MultiKey, [], AddData, TupleResultList) -> [AddData | TupleResultList];
multikeystore(MultiKey, [H | L], AddData, TupleResultList) ->
    case match_muilt_key(MultiKey, H) of
        true ->
            R = lists:reverse(TupleResultList),
            R ++ [AddData] ++ L;
        false -> multikeystore(MultiKey, L, AddData, [H | TupleResultList])
    end.

%% ==================================
%% @doc 取列表的前N个元素， 不足N个返回整个列表, 返回列表不关心顺序
%% ==================================
-spec forward(L :: list(), N :: integer()) -> list().
forward(L, N) ->
    forward(L, N, []).
forward([], _, List) -> List;
forward(_, N, List) when N =< 0 -> List;
forward([H | L], N, List) ->
    forward(L, N - 1, [H | List]).


%% ======================
%% 内部函数
%% ======================
match_muilt_key([], _) -> true;
match_muilt_key([{Key, Pos} | L], Data) ->
    case match_key(Key, Pos, Data) of
        true -> match_muilt_key(L, Data);
        false -> false
    end;
match_muilt_key([_ | L], Data) ->
    match_muilt_key(L, Data).

match_key(Key, Pos, Data) when is_integer(Pos) andalso tuple_size(Data) >= Pos andalso Pos >= 1 ->
    element(Pos, Data) =:= Key;
match_key(_, _, _) ->
    false.

%%无重复合并列表
umerge_add([], List) -> List;
umerge_add([H | T], List) ->
    umerge_add(T, ustore(H, List)).

%%按key值无重复合并
key_replace(_N, [], List) -> List;
key_replace(N, [E | AddList], PerList) ->
    Key = element(N, E),
    PerList2 = lists:keystore(Key, N, PerList, E),
    key_replace(N, AddList, PerList2).


%%重置排名
loop_index(L, RankIndex) ->
    loop_index(L, 1, RankIndex, []).

%%重置排名
loop_index([], _I, _Index, Ret) -> Ret;
loop_index([E | T], I, RankIndex, Ret) ->
    NewE = setelement(RankIndex, E, I),
    loop_index(T, I + 1, RankIndex, [NewE | Ret]).


%% 判断列表是否有重复项：true-有重复项 false-无重复项
is_repetition([]) ->
    false;
is_repetition([H | List]) ->
    case lists:member(H, List) of
        true ->     %% 有重复项
            true;
        _ ->
            is_repetition(List)
    end.

%% 判断列表是否全部重复：true - 全是重复项 false - 有非重复项
is_urepetition([]) ->
    true;
is_urepetition([_]) ->
    true;
is_urepetition([H | List]) ->
    case lists:member(H, List) of
        true ->     %% 有重复项
            is_urepetition(List);
        _ ->
            false
    end.

%% 指定分隔符来拼接字符串
concat(List, Code) ->
    do_concat(List, Code, "").

do_concat([], _Code, Msg) ->
    Msg;
do_concat(["" | T], Code, Msg) ->
    do_concat(T, Code, Msg);
do_concat([S | T], Code, Msg) ->
    NewMsg = ?iif(Msg == "", S, lists:concat([Msg, Code, S])),
    do_concat(T, Code, NewMsg).

%%批量替换列表键值
mkeystore([], _KeyIndex, List) -> List;
mkeystore([KV | T], KeyIndex, List) when is_tuple(KV) ->
    K = element(KeyIndex, KV),
    mkeystore(T, KeyIndex, lists:keystore(K, KeyIndex, List, KV)).